#!/bin/sh
#Edit-SFS version 2.0
#by Pizzagood <pizzasgood@gmail.com>
#Copyright under the GNU Lesser General Public License (LGPL)
#2009.10.05: creation

TITLE="Edit-SFS"

APPDIR="$(dirname "$0")"
APPNAME="$(basename "$0")"
PATH_FILE="$APPDIR/basepath"
RAMDISK_FILE="$APPDIR/ramdisk"


#find out what type of partition a directory is on
whatpartitiontype(){
    DIR="$(realpath "$1")"
    MOUNT_OUTPUT="$(mount | grep "^[^ ]* on $DIR ")"
    if [ "$MOUNT_OUTPUT" = "" ]; then
        whatpartitiontype "$(dirname "$DIR")"
    else
        DEVNODE="$(echo "$MOUNT_OUTPUT" | cut -f 1 -d ' ')"
        probepart | grep "^$DEVNODE|" | cut -f 2 -d '|'
    fi
}

#find out if a directory is on a linux partition
#(actually, just rule out non-linux partitions)
isnixpartition(){
    TYPE="$(whatpartitiontype "$1")"
    case "$TYPE" in
        vfat|fat*|msdos|ntfs)
            echo "false"
            return 1
            ;;
        *)
            echo "true"
            return 0
            ;;
    esac
}

#get the base directory
get_base_dir_to_use(){
    [ -e "$PATH_FILE" ] && BASE="$(cat "$PATH_FILE")"
    while [ "$BASE" = "" ] || [ ! -d "$BASE" ]; do
        prompt_for_base_dir
        [ -e "$PATH_FILE" ] && BASE="$(cat "$PATH_FILE")"
    done
    [ -e "$RAMDISK_FILE" ] && RAMDISK="true"
}

#prompt the user for a directory to work in
prompt_for_base_dir(){
    if [ "$1" != "" ]; then
        STARTDIR="$1"
    else
        STARTDIR="/"
    fi
    #prompt for whether to use a normal location or a ramdisk
    Xdialog --title "$TITLE" --ok-label "Parition" --cancel-label "Ramdisk" --yesno "You must define a working directory.\n\nYou should choose a location on a linux partition\nwith several hundred megabytes of free space.\nIf you don't have a suitable location but\ndo have plenty of ram, you can use a ramdisk." 0 0
    RET=$?
    if [ $RET -eq 0 ]; then
        #find out what location they want to use
        while [ "$BASE" = "" ]; do
            ATTEMPTED_BASE="$(Xdialog --title "$TITLE" --dselect "$STARTDIR" 0 0 2>&1)"
            RET=$?
            if [ $RET -eq 0 ]; then
                #have them confirm, because the use of Xdialog's fselect deal may not be obvious at first
                Xdialog --title "$TITLE" --yesno "You have chosen to use: $ATTEMPTED_BASE\nIf you are satisfied with this choice, press 'Yes'.\nOtherwise press 'No' to chose again." 0 0
                RET=$?
                if [ $RET -eq 0 ]; then
                    #trim off any trailing /
                    BASE="$(echo "$ATTEMPTED_BASE" | sed 's|\(.\)/*$|\1|')"
                    echo "$BASE" > "$PATH_FILE"
                    rm -f "$RAMDISK_FILE"
                elif [ $RET != 1 ]; then
                    exit 255
                fi
            else
                exit 255
            fi
        done
    elif [ $RET -eq 1 ]; then
        #if using a ramdisk, go ahead and put the base in /tmp.  A unique temporary
        #directory will be created there later, and the ramdisk will be mounted on that.
        echo "/tmp" > "$PATH_FILE"
        echo "ramdisk" > "$RAMDISK_FILE"
    else
        exit 255
    fi
}

#detect and handle sfs files from other versions
sfs_expand(){
    SOURCE="$1"
    DESTDIR="$2"
    [ ! -f "$SOURCE" ] && exit 4
    
    KERNELVER="$(uname -r)"
    KERNELSUBVER=$(echo -n "$KERNELVER" | cut -f 3 -d '.' | cut -f 1 -d '-')
    SFSVERSION="3"
    [ $KERNELSUBVER -gt 28 ] && SFSVERSION="4"
    SFSSTR="squashfs, version $SFSVERSION"

    #check if it's an incompatible version
    if [ "$(disktype "$SOURCE" | grep "$SFSSTR")" = "" ]; then
        #update the SFSVERSION so that the final file will be of the same version as the original
        if [ "$SFSVERSION" = "4" ]; then
            SFSVERSION="3"
        else
            SFSVERSION="4"
        fi
    fi

    #decide what mksquashfs program to use for later
    MKSQUASHFS="mksquashfs$SFSVERSION"
    [ "$(which "$MKSQUASHFS")" = "" ] && MKSQUASHFS="mksquashfs"


    #try to extract it with unsquashfs
    UNSQUASHFSOUT="$(unsquashfs -d "$DESTDIR" "$SOURCE" 2>&1 >/dev/null)"
    RET=$?
    if [ $RET -ne 0 ]; then
        ERRORMSG="ERROR - unsquashfs failed to expand $SOURCE\nIt returned the following error message:\n$UNSQUASHFSOUT"
        echo -e "$ERRORMSG" 2>&1
        Xdialog --title "$TITLE" --msgbox "$ERRORMSG" 0 0

        #clean up
        rox -D "$TREE_BASE"
        [ "$RAMDISK" != "" ] && umount "$TREE_BASE"
        rm -r "$TREE_BASE"

        exit 5
    fi

}





#let the user change the base dir options
if [ "$1" = "--setbasedir" ]; then
    prompt_for_base_dir
    exit 0
fi





#get path to .sfs file
if [ "$1" != "" ]; then
    ORIGFILE="$1"
else
    #nothing was provided, so prompt the user
    export GUI="
<window title=\"$TITLE\" icon-name=\"gtk-file\">
<vbox>
  <text><label>Please either enter the path to the .sfs file you wish to edit, or drag and drop the file into the text field.</label></text>
   <text use-markup=\"true\"><label>\"<b>For file encryption or decryption, drag the file here</b>\"</label></text>          
  <hbox>
  <entry accept=\"directory\"><variable>SOURCEFILE</variable></entry>
  </hbox>         
  <hbox>
  <button cancel></button>
  <button ok></button>
  </hbox>
</vbox>
</window>"

    RETVALS="`gtkdialog3 --program=GUI --center`"
    if [ "$(echo "$RETVALS" | grep '^EXIT="OK"$')" = "" ]; then
        exit 1
    else
        ORIGFILE="$(echo "$RETVALS" | grep '^SOURCEFILE=".*"$' | sed 's|^SOURCEFILE="\(.*\)"$|\1|')"
    fi
fi

if [ ! -f "$ORIGFILE" ]; then
    echo "ERROR - No such file: $ORIGFILE" >&2
    exit 1
fi
SFSFILE="$(basename "$ORIGFILE")"


#chose a location for the working tree
get_base_dir_to_use
if [ ! -d "$BASE" ]; then
    echo "ERROR - No such directory $BASE" >&2
    exit 2
fi
TREE_BASE="$(mktemp -d -p "$BASE")"
if [ ! -d "$TREE_BASE" ]; then
    echo "ERROR - No such directory $TREE_BASE" >&2
    exit 3
fi
[ "$RAMDISK" != "" ] && mount -t tmpfs tmpfs "$TREE_BASE"
TREE="${TREE_BASE}/working_tree"
[ -e "$TREE" ] && rm -rf "$TREE"




#extract $ORIGFILE to $TREE
sfs_expand "$ORIGFILE" "$TREE"

#Change window to $TREE for editing
rox "$TREE"
Xdialog --title "$TITLE" --ok-label "Build" --msgbox "You may now edit things to your heart's content.
Click 'Build' when ready to build the new file." 0 0




#Use mksquashfs to put it back together
rox -D "$TREE"
echo -e "#!/bin/sh\n'$MKSQUASHFS' '$TREE' '$TREE_BASE/$SFSFILE'" > "${TREE_BASE}/script"
chmod +x "${TREE_BASE}/script"
rxvt -geometry 80x4 -e "${TREE_BASE}/script"
rm "${TREE_BASE}/script"
sync

#Remove $TREE to stay tidy
rox -D "$TREE"
rm -r "$TREE" 

#Pop window up for giving *.sfs back
rox "$TREE_BASE"
Xdialog --title "$TITLE" --ok-label "Finished" --msgbox "Okay, $SFSFILE is ready.  Place it wherever you want, then hit 'Finished'.
NOTE:  When you click the button, this copy of $SFSFILE will be deleted,
along with this directory!" 0 0

#clean up
rox -D "$TREE_BASE"
[ "$RAMDISK" != "" ] && umount "$TREE_BASE"
rm -r "$TREE_BASE"

#All done.  Have a good day!
Xdialog --title "$TITLE" --msgbox "All finished.  Have a good day!" 0 0

